/*
 * zfunc - extended precision integral arithmetic non-primitive routines
 *
 * Copyright (C) 1999-2007  David I. Bell, Landon Curt Noll and Ernest Bowen
 *
 * Primary author:  David I. Bell
 *
 * Calc is open software; you can redistribute it and/or modify it under
 * the terms of the version 2.1 of the GNU Lesser General Public License
 * as published by the Free Software Foundation.
 *
 * Calc is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU Lesser General
 * Public License for more details.
 *
 * A copy of version 2.1 of the GNU Lesser General Public License is
 * distributed with calc under the filename COPYING-LGPL.  You should have
 * received a copy with calc; if not, write to Free Software Foundation, Inc.
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 * @(#) $Revision: 30.2 $
 * @(#) $Id: zfunc.c,v 30.2 2008/02/24 07:41:49 chongo Exp $
 * @(#) $Source: /usr/local/src/cmd/calc/RCS/zfunc.c,v $
 *
 * Under source code control:	1990/02/15 01:48:27
 * File existed as early as:	before 1990
 *
 * Share and enjoy!  :-)	http://www.isthe.com/chongo/tech/comp/calc/
 */


#include "zmath.h"

ZVALUE _tenpowers_[TEN_MAX+1];		/* table of 10^2^n */

STATIC long *power10 = NULL;
STATIC int max_power10_exp = 0;

/*
 * given:
 *
 *	unsigned long x
 * or:	unsigned long long x
 * or:	long x			and  x >= 0
 * or:	long long x		and  x >= 0
 *
 * If issq_mod4k[x & 0xfff] == 0, then x cannot be a perfect square
 * else x might be a perfect square.
 */
STATIC USB8 issq_mod4k[1<<12] = {
	1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
	0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
};


/*
 * Compute the factorial of a number.
 */
void
zfact(ZVALUE z, ZVALUE *dest)
{
	long ptwo;		/* count of powers of two */
	long n;			/* current multiplication value */
	long m;			/* reduced multiplication value */
	long mul;		/* collected value to multiply by */
	ZVALUE res, temp;

	if (zisneg(z)) {
		math_error("Negative argument for factorial");
		/*NOTREACHED*/
	}
	if (zge31b(z)) {
		math_error("Very large factorial");
		/*NOTREACHED*/
	}
	n = ztolong(z);
	ptwo = 0;
	mul = 1;
	res = _one_;
	/*
	 * Multiply numbers together, but squeeze out all powers of two.
	 * We will put them back in at the end.	 Also collect multiple
	 * numbers together until there is a risk of overflow.
	 */
	for (; n > 1; n--) {
		for (m = n; ((m & 0x1) == 0); m >>= 1)
			ptwo++;
		if (mul <= MAXLONG/m) {
			mul *= m;
			continue;
		}
		zmuli(res, mul, &temp);
		zfree(res);
		res = temp;
		mul = m;
	}
	/*
	 * Multiply by the remaining value, then scale result by
	 * the proper power of two.
	 */
	if (mul > 1) {
		zmuli(res, mul, &temp);
		zfree(res);
		res = temp;
	}
	zshift(res, ptwo, &temp);
	zfree(res);
	*dest = temp;
}


/*
 * Compute the permutation function  M! / (M - N)!.
 */
void
zperm(ZVALUE z1, ZVALUE z2, ZVALUE *res)
{
	SFULL count;
	ZVALUE cur, tmp, ans;

	if (zisneg(z1) || zisneg(z2)) {
		math_error("Negative argument for permutation");
		/*NOTREACHED*/
	}
	if (zrel(z1, z2) < 0) {
		math_error("Second arg larger than first in permutation");
		/*NOTREACHED*/
	}
	if (zge31b(z2)) {
		math_error("Very large permutation");
		/*NOTREACHED*/
	}
	count = ztolong(z2);
	zcopy(z1, &ans);
	zsub(z1, _one_, &cur);
	while (--count > 0) {
		zmul(ans, cur, &tmp);
		zfree(ans);
		ans = tmp;
		zsub(cur, _one_, &tmp);
		zfree(cur);
		cur = tmp;
	}
	zfree(cur);
	*res = ans;
}

/*
 * docomb evaluates binomial coefficient when z1 >= 0, z2 >= 0
 */
S_FUNC int
docomb(ZVALUE z1, ZVALUE z2, ZVALUE *res)
{
	ZVALUE ans;
	ZVALUE mul, div, temp;
	FULL count, i;
#if BASEB == 16
	HALF dh[2];
#else
	HALF dh[1];
#endif

	if (zrel(z2, z1) > 0)
		return 0;
	zsub(z1, z2, &temp);

	if (zge31b(z2) && zge31b(temp)) {
		zfree(temp);
		return -2;
	}
	if (zrel(temp, z2) < 0)
		count = ztofull(temp);
	else
		count = ztofull(z2);
	zfree(temp);
	if (count == 0)
		return 1;
	if (count == 1)
		return 2;
	div.sign = 0;
	div.v = dh;
	div.len = 1;
	zcopy(z1, &mul);
	zcopy(z1, &ans);
	for (i = 2; i <= count; i++) {
#if BASEB == 16
		dh[0] = (HALF)(i & BASE1);
		dh[1] = (HALF)(i >> BASEB);
		div.len = 1 + (dh[1] != 0);
#else
		dh[0] = (HALF) i;
#endif
		zsub(mul, _one_, &temp);
		zfree(mul);
		mul = temp;
		zmul(ans, mul, &temp);
		zfree(ans);
		zquo(temp, div, &ans, 0);
		zfree(temp);
	}
	zfree(mul);
	*res = ans;
	return 3;
}

/*
 * Compute the combinatorial function  M! / ( N! * (M - N)! ).
 * Returns 0 if result is 0
*	   1      1
*	   2      z1
*	  -1	  -1
*	  -2	if too complicated
*	   3	result stored at res
 */
int
zcomb(ZVALUE z1, ZVALUE z2, ZVALUE *res)
{
	ZVALUE z3, z4;
	int r;

	if (z2.sign || (!z1.sign && zrel(z2, z1) > 0))
		return 0;
	if (zisone(z2))
		return 2;
	if (z1.sign) {
		z1.sign = 0;
		zsub(z1, _one_, &z3);
		zadd(z3, z2, &z4);
		zfree(z3);
		r = docomb(z4, z2, res);
		if (r == 2) {
			*res = z4;
			r = 3;
		}
		else
			zfree(z4);
		if (z2.v[0] & 1) {
			if (r == 1)
				r = -1;
			if (r == 3)
				res->sign = 1;
		}
		return r;
	}
	return docomb(z1, z2, res);
}


/*
 * Compute the Jacobi function (m / n) for odd n.
 *
 * The property of the Jacobi function is: If n>2 is prime then
 *
 *	the result is 1 if m == x^2 (mod n) for some x.
 *	otherwise the result is -1.
 *
 * If n is not prime, then the result does not prove that n is not prine
 * when the value of the Jacobi is 1.
 *
 * Jacobi evaluation of (m / n), where n > 0 is odd AND m > 0 is odd:
 *
 *	rule 0:	(0 / n) == 0
 *	rule 1:	(1 / n) == 1
 *	rule 2:	(m / n) == (a / n)	if m == a % n
 *	rule 3:	(m / n) == (2*m / n)	if n == 1 % 8 OR n == 7 % 8
 *	rule 4:	(m / n) == -(2*m / n)	if n != 1 & 8 AND n != 7 % 8
 *	rule 5:	(m / n) == (n / m)	if m == 3 % 4 AND n == 3 % 4
 *	rule 6:	(m / n) == -(n / m)	if m != 3 % 4 OR n != 3 % 4
 *
 * NOTE: This function returns 0 in invalid Jacobi parameters:
 *	 m < 0 OR n is even OR n < 1.
 */
FLAG
zjacobi(ZVALUE z1, ZVALUE z2)
{
	ZVALUE p, q, tmp;
	long lowbit;
	int val;

	/* firewall */
	if (ziszero(z1) || zisneg(z1))
		return 0;
	if (ziseven(z2) || zisneg(z2))
		return 0;

	/* assume a value of 1 unless we find otherwise */
	if (zisone(z1))
		return 1;
	val = 1;
	zcopy(z1, &p);
	zcopy(z2, &q);
	for (;;) {
		zmod(p, q, &tmp, 0);
		zfree(p);
		p = tmp;
		if (ziszero(p)) {
			zfree(p);
			zfree(q);
			return 0;
		}
		if (ziseven(p)) {
			lowbit = zlowbit(p);
			zshift(p, -lowbit, &tmp);
			zfree(p);
			p = tmp;
			if ((lowbit & 1) && (((*q.v & 0x7) == 3) || ((*q.v & 0x7) == 5)))
				val = -val;
		}
		if (zisunit(p)) {
			zfree(p);
			zfree(q);
			return val;
		}
		if ((*p.v & *q.v & 0x3) == 3)
			val = -val;
		tmp = q;
		q = p;
		p = tmp;
	}
}


/*
 * Return the Fibonacci number F(n).
 * This is evaluated by recursively using the formulas:
 *	F(2N+1) = F(N+1)^2 + F(N)^2
 * and
 *	F(2N) = F(N+1)^2 - F(N-1)^2
 */
void
zfib(ZVALUE z, ZVALUE *res)
{
	long n;
	int sign;
	ZVALUE fnm1, fn, fnp1;		/* consecutive fibonacci values */
	ZVALUE t1, t2, t3;
	FULL i;

	if (zge31b(z)) {
		math_error("Very large Fibonacci number");
		/*NOTREACHED*/
	}
	n = ztolong(z);
	if (n == 0) {
		*res = _zero_;
		return;
	}
	sign = z.sign && ((n & 0x1) == 0);
	if (n <= 2) {
		*res = _one_;
		res->sign = (BOOL)sign;
		return;
	}
	i = TOPFULL;
	while ((i & n) == 0)
		i >>= (FULL)1;
	i >>= (FULL)1;
	fnm1 = _zero_;
	fn = _one_;
	fnp1 = _one_;
	while (i) {
		zsquare(fnm1, &t1);
		zsquare(fn, &t2);
		zsquare(fnp1, &t3);
		zfree(fnm1);
		zfree(fn);
		zfree(fnp1);
		zadd(t2, t3, &fnp1);
		zsub(t3, t1, &fn);
		zfree(t1);
		zfree(t2);
		zfree(t3);
		if (i & n) {
			fnm1 = fn;
			fn = fnp1;
			zadd(fnm1, fn, &fnp1);
		} else {
			zsub(fnp1, fn, &fnm1);
		}
		i >>= (FULL)1;
	}
	zfree(fnm1);
	zfree(fnp1);
	*res = fn;
	res->sign = (BOOL)sign;
}


/*
 * Compute the result of raising one number to the power of another
 * The second number is assumed to be non-negative.
 * It cannot be too large except for trivial cases.
 */
void
zpowi(ZVALUE z1, ZVALUE z2, ZVALUE *res)
{
	int sign;		/* final sign of number */
	unsigned long power;	/* power to raise to */
	FULL bit;		/* current bit value */
	long twos;		/* count of times 2 is in result */
	ZVALUE ans, temp;

	sign = (z1.sign && zisodd(z2));
	z1.sign = 0;
	z2.sign = 0;
	if (ziszero(z2) && !ziszero(z1)) {	/* number raised to power 0 */
		*res = _one_;
		return;
	}
	if (zisabsleone(z1)) {	/* 0, 1, or -1 raised to a power */
		ans = _one_;
		ans.sign = (BOOL)sign;
		if (*z1.v == 0)
			ans = _zero_;
		*res = ans;
		return;
	}
	if (zge31b(z2)) {
		math_error("Raising to very large power");
		/*NOTREACHED*/
	}
	power = ztoulong(z2);
	if (zistwo(z1)) {	/* two raised to a power */
		zbitvalue((long) power, res);
		return;
	}
	/*
	 * See if this is a power of ten
	 */
	if (zistiny(z1) && (*z1.v == 10)) {
		ztenpow((long) power, res);
		res->sign = (BOOL)sign;
		return;
	}
	/*
	 * Handle low powers specially
	 */
	if (power <= 4) {
		switch ((int) power) {
		case 1:
			ans.len = z1.len;
			ans.v = alloc(ans.len);
			zcopyval(z1, ans);
			ans.sign = (BOOL)sign;
			*res = ans;
			return;
		case 2:
			zsquare(z1, res);
			return;
		case 3:
			zsquare(z1, &temp);
			zmul(z1, temp, res);
			zfree(temp);
			res->sign = (BOOL)sign;
			return;
		case 4:
			zsquare(z1, &temp);
			zsquare(temp, res);
			zfree(temp);
			return;
		}
	}
	/*
	 * Shift out all powers of twos so the multiplies are smaller.
	 * We will shift back the right amount when done.
	 */
	twos = 0;
	if (ziseven(z1)) {
		twos = zlowbit(z1);
		ans.v = alloc(z1.len);
		ans.len = z1.len;
		ans.sign = z1.sign;
		zcopyval(z1, ans);
		zshiftr(ans, twos);
		ztrim(&ans);
		z1 = ans;
		twos *= power;
	}
	/*
	 * Compute the power by squaring and multiplying.
	 * This uses the left to right method of power raising.
	 */
	bit = TOPFULL;
	while ((bit & power) == 0)
		bit >>= 1;
	bit >>= 1;
	zsquare(z1, &ans);
	if (bit & power) {
		zmul(ans, z1, &temp);
		zfree(ans);
		ans = temp;
	}
	bit >>= 1;
	while (bit) {
		zsquare(ans, &temp);
		zfree(ans);
		ans = temp;
		if (bit & power) {
			zmul(ans, z1, &temp);
			zfree(ans);
			ans = temp;
		}
		bit >>= 1;
	}
	/*
	 * Scale back up by proper power of two
	 */
	if (twos) {
		zshift(ans, twos, &temp);
		zfree(ans);
		ans = temp;
		zfree(z1);
	}
	ans.sign = (BOOL)sign;
	*res = ans;
}


/*
 * Compute ten to the specified power
 * This saves some work since the squares of ten are saved.
 */
void
ztenpow(long power, ZVALUE *res)
{
	long i;
	ZVALUE ans;
	ZVALUE temp;

	if (power <= 0) {
		*res = _one_;
		return;
	}
	ans = _one_;
	_tenpowers_[0] = _ten_;
	for (i = 0; power; i++) {
		if (_tenpowers_[i].len == 0) {
			if (i <= TEN_MAX) {
				zsquare(_tenpowers_[i-1], &_tenpowers_[i]);
			} else {
				math_error("cannot compute 10^2^(TEN_MAX+1)");
				/*NOTREACHED*/
			}
		}
		if (power & 0x1) {
			zmul(ans, _tenpowers_[i], &temp);
			zfree(ans);
			ans = temp;
		}
		power /= 2;
	}
	*res = ans;
}


/*
 * Calculate modular inverse suppressing unnecessary divisions.
 * This is based on the Euclidean algorithm for large numbers.
 * (Algorithm X from Knuth Vol 2, section 4.5.2. and exercise 17)
 * Returns TRUE if there is no solution because the numbers
 * are not relatively prime.
 */
BOOL
zmodinv(ZVALUE u, ZVALUE v, ZVALUE *res)
{
	FULL	q1, q2, ui3, vi3, uh, vh, A, B, C, D, T;
	ZVALUE	u2, u3, v2, v3, qz, tmp1, tmp2, tmp3;

	v.sign = 0;
	if (zisneg(u) || (zrel(u, v) >= 0))
		zmod(u, v, &v3, 0);
	else
		zcopy(u, &v3);
	zcopy(v, &u3);
	u2 = _zero_;
	v2 = _one_;

	/*
	 * Loop here while the size of the numbers remain above
	 * the size of a HALF.	Throughout this loop u3 >= v3.
	 */
	while ((u3.len > 1) && !ziszero(v3)) {
		vh = 0;
#if LONG_BITS == BASEB
		uh =  u3.v[u3.len - 1];
		if (v3.len == u3.len)
			vh = v3.v[v3.len - 1];
#else
		uh = (((FULL) u3.v[u3.len - 1]) << BASEB) + u3.v[u3.len - 2];
		if ((v3.len + 1) >= u3.len)
			vh = v3.v[v3.len - 1];
		if (v3.len == u3.len)
			vh = (vh << BASEB) + v3.v[v3.len - 2];
#endif
		A = 1;
		B = 0;
		C = 0;
		D = 1;

		/*
		 * Calculate successive quotients of the continued fraction
		 * expansion using only single precision arithmetic until
		 * greater precision is required.
		 */
		while ((vh + C) && (vh + D)) {
			q1 = (uh + A) / (vh + C);
			q2 = (uh + B) / (vh + D);
			if (q1 != q2)
				break;
			T = A - q1 * C;
			A = C;
			C = T;
			T = B - q1 * D;
			B = D;
			D = T;
			T = uh - q1 * vh;
			uh = vh;
			vh = T;
		}

		/*
		 * If B is zero, then we made no progress because
		 * the calculation requires a very large quotient.
		 * So we must do this step of the calculation in
		 * full precision
		 */
		if (B == 0) {
			zquo(u3, v3, &qz, 0);
			zmul(qz, v2, &tmp1);
			zsub(u2, tmp1, &tmp2);
			zfree(tmp1);
			zfree(u2);
			u2 = v2;
			v2 = tmp2;
			zmul(qz, v3, &tmp1);
			zsub(u3, tmp1, &tmp2);
			zfree(tmp1);
			zfree(u3);
			u3 = v3;
			v3 = tmp2;
			zfree(qz);
			continue;
		}
		/*
		 * Apply the calculated A,B,C,D numbers to the current
		 * values to update them as if the full precision
		 * calculations had been carried out.
		 */
		zmuli(u2, (long) A, &tmp1);
		zmuli(v2, (long) B, &tmp2);
		zadd(tmp1, tmp2, &tmp3);
		zfree(tmp1);
		zfree(tmp2);
		zmuli(u2, (long) C, &tmp1);
		zmuli(v2, (long) D, &tmp2);
		zfree(u2);
		zfree(v2);
		u2 = tmp3;
		zadd(tmp1, tmp2, &v2);
		zfree(tmp1);
		zfree(tmp2);
		zmuli(u3, (long) A, &tmp1);
		zmuli(v3, (long) B, &tmp2);
		zadd(tmp1, tmp2, &tmp3);
		zfree(tmp1);
		zfree(tmp2);
		zmuli(u3, (long) C, &tmp1);
		zmuli(v3, (long) D, &tmp2);
		zfree(u3);
		zfree(v3);
		u3 = tmp3;
		zadd(tmp1, tmp2, &v3);
		zfree(tmp1);
		zfree(tmp2);
	}

	/*
	 * Here when the remaining numbers become single precision in size.
	 * Finish the procedure using single precision calculations.
	 */
	if (ziszero(v3) && !zisone(u3)) {
		zfree(u3);
		zfree(v3);
		zfree(u2);
		zfree(v2);
		return TRUE;
	}
	ui3 = ztofull(u3);
	vi3 = ztofull(v3);
	zfree(u3);
	zfree(v3);
	while (vi3) {
		q1 = ui3 / vi3;
		zmuli(v2, (long) q1, &tmp1);
		zsub(u2, tmp1, &tmp2);
		zfree(tmp1);
		zfree(u2);
		u2 = v2;
		v2 = tmp2;
		q2 = ui3 - q1 * vi3;
		ui3 = vi3;
		vi3 = q2;
	}
	zfree(v2);
	if (ui3 != 1) {
		zfree(u2);
		return TRUE;
	}
	if (zisneg(u2)) {
		zadd(v, u2, res);
		zfree(u2);
		return FALSE;
	}
	*res = u2;
	return FALSE;
}


/*
 * Compute the greatest common divisor of a pair of integers.
 */
void
zgcd(ZVALUE z1, ZVALUE z2, ZVALUE *res)
{
	int h, i, j, k;
	LEN len, l, m, n, o, p, q;
	HALF u, v, w, x;
	HALF *a, *a0, *A, *b, *b0, *B, *c, *d;
	FULL f, g;
	ZVALUE gcd;
	BOOL needw;

	if (zisunit(z1) || zisunit(z2)) {
		*res = _one_;
		return;
	}
	z1.sign = 0;
	z2.sign = 0;
	if (ziszero(z1) || !zcmp(z1, z2)) {
		zcopy(z2, res);
		return;
	}
	if (ziszero(z2)) {
		zcopy(z1, res);
		return;
	}

	o = 0;
	while (!(z1.v[o] | z2.v[o])) o++;	/* Count common zero digits */

	c = z1.v + o;
	d = z2.v + o;

	m = z1.len - o;
	n = z2.len - o;
	u = *c | *d;			/* Count common zero bits */
	v = 1;
	p = 0;
	while (!(u & v)) {
		v <<= 1;
		p++;
	}

	while (!*c) {				/* Removing zero digits */
		c++;
		m--;
	}

	while (!*d) {
		d++;
		n--;
	}


	u = *d;			/* Count zero bits for *d */
	v = 1;
	q = 0;
	while (!(u & v)) {
		v <<= 1;
		q++;
	}

	a0 = A = alloc(m);
	b0 = B = alloc(n);

	memcpy(A, c, m * sizeof(HALF));			/* Copy c[] to A[] */

				/* Copy d[] to B[], shifting if necessary */
	if (q) {
		i = n;
		b = B + n;
		d += n;
		f = 0;
		while (i--) {
			f = f << BASEB | *--d;
			*--b = (HALF) (f >> q);
		}
		if (B[n-1] == 0) n--;
	}
	else memcpy(B, d, n * sizeof(HALF));

	if (n == 1) {		/* One digit case; use Euclid's algorithm */
		n = m;
		b0 = A;
		m = 1;
		a0 = B;
		if (m == 1) {				/* a has one digit */
			v = *a0;
			if (v > 1) {			/* Euclid's algorithm */
				b = b0 + n;
				i = n;
				u = 0;
				while (i--) {
					f = (FULL) u << BASEB | *--b;
					u = (HALF) (f % v);
				}
				while (u) { w = v % u; v = u; u = w; }
			}
			*b0 = v;
			n = 1;
		}
		len = n + o;
		gcd.v = alloc(len + 1);
		/* Common zero digits */
		if (o) memset(gcd.v, 0, o * sizeof(HALF));
		/* Left shift for common zero bits */
		if (p) {
			i = n;
			f = 0;
			b = b0;
			a = gcd.v + o;
			while (i--) {
				f = f >> BASEB | (FULL) *b++ << p;
				*a++ = (HALF) f;
			}
			if (f >>= BASEB) {len++; *a = (HALF) f;}
		} else {
			memcpy(gcd.v + o, b0, n * sizeof(HALF));
		}
		gcd.len = len;
		gcd.sign = 0;
		freeh(A);
		freeh(B);
		*res = gcd;
		return;
	}

	u = B[n-1];				/* Bit count for b */
	k = (n	- 1) * BASEB;
	while (u >>= 1) k++;

	needw = TRUE;

	w = 0;
	j = 0;
	while (m) {				/* START OF MAIN LOOP */
	   if (m - n < 2 || needw) {
		q = 0;
		u = *a0;
		v = 1;
		while (!(u & v)) {		/* count zero bits for *a0 */
			q++;
			v <<= 1;
		}

		if (q) {			/* right-justify a */
			a = a0 + m;
			i = m;
			f = 0;
			while (i--) {
				f = f << BASEB | *--a;
				*a = (HALF) (f >> q);
			}
			if (!a0[m-1]) m--;	/* top digit vanishes */
		}

		if (m == 1) break;

		u = a0[m-1];
		j = (m - 1) * BASEB;
		while (u >>= 1) j++;		/* counting bits for a */
		h = j - k;
		if (h < 0) {			/* swapping to get h > 0 */
			l = m;
			m = n;
			n = l;
			a = a0;
			a0 = b0;
			b0 = a;
			k = j;
			h = -h;
			needw = TRUE;
		}
		if (h > 1) {
			if (needw) {		/* find w = minv(*b0, h0) */
				u = 1;
				v = *b0;
				w = 0;
				x = 1;
				i = h;
				while (i-- && x) {
					if (u & x) { u -= v * x; w |= x;}
					x <<= 1;
				}
				needw = FALSE;
			}
			g = *a0 * w;
			if (h < BASEB) g &= (1 << h) - 1;
			else g &= BASE1;
		}
		else g = 1;
	   } else
		g = (HALF) *a0 * w;
		a = a0;
		b = b0;
		i = n;
		if (g > 1) {			/* a - g * b case */
			f = 0;
			while (i--) {
				f = (FULL) *a - g * *b++ - f;
				*a++ = (HALF) f;
				f >>= BASEB;
				f = -f & BASE1;
			}
			if (f) {
				i = m - n;
				while (i-- && f) {
					f = *a - f;
					*a++ = (HALF) f;
					f >>= BASEB;
					f = -f & BASE1;
				}
			}
			while (m && !*a0) { /* Removing trailing zeros */
				m--;
				a0++;
			}
			if (f) {		/* a - g * b < 0 */
				while (m > 1 && a0[m-1] == BASE1) m--;
				*a0 = - *a0;
				a = a0;
				i = m;
				while (--i) {
					a++;
					*a = ~*a;
				}
			}
		} else {				/* abs(a - b) case */
			while (i && *a++ == *b++) i--;
			q = n - i;
			if (m == n) {		/* a and b same length */
				if (i) {	 /* a not equal to b */
					while (m && a0[m-1] == b0[m-1]) m--;
					if (a0[m-1] < b0[m-1]) {
						/* Swapping since a < b */
						a = a0;
						a0 = b0;
						b0 = a;
						k = j;
					}
					a = a0 + q;
					b = b0 + q;
					i = m - q;
					f = 0;
					while (i--) {
						f = (FULL) *a - *b++ - f;
						*a++ = (HALF) f;
						f >>= BASEB;
						f = -f & BASE1;
					}
				}
			} else {		/* a has more digits than b */
				a = a0 + q;
				b = b0 + q;
				i = n - q;
				f = 0;
				while (i--) {
					f = (FULL) *a - *b++ - f;
					*a++ = (HALF) f;
					f >>= BASEB;
					f = -f & BASE1;
				}
				if (f) { while (!*a) *a++ = BASE1;
					(*a)--;
				}
			}
			a0 += q;
			m -= q;
			while (m && !*a0) { /* Removing trailing zeros */
				m--;
				a0++;
			}
		}
		while (m && !a0[m-1]) m--;	/* Removing leading zeros */
	}
	if (m == 1) {				/* a has one digit */
		v = *a0;
		if (v > 1) {			/* Euclid's algorithm */
			b = b0 + n;
			i = n;
			u = 0;
			while (i--) {
				f = (FULL) u << BASEB | *--b;
				u = (HALF) (f % v);
			}
			while (u) { w = v % u; v = u; u = w; }
		}
		*b0 = v;
		n = 1;
	}
	len = n + o;
	gcd.v = alloc(len + 1);
	if (o) memset(gcd.v, 0, o * sizeof(HALF));	/* Common zero digits */
	if (p) {			/* Left shift for common zero bits */
		i = n;
		f = 0;
		b = b0;
		a = gcd.v + o;
		while (i--) {
			f = (FULL) *b++ << p | f;
			*a++ = (HALF) f;
			f >>= BASEB;
		}
		if (f) {
			len++; *a = (HALF) f;
		}
	} else {
		memcpy(gcd.v + o, b0, n * sizeof(HALF));
	}
	gcd.len = len;
	gcd.sign = 0;
	freeh(A);
	freeh(B);
	*res = gcd;
	return;
}

/*
 * Compute the lcm of two integers (least common multiple).
 * This is done using the formula:  gcd(a,b) * lcm(a,b) = a * b.
 */
void
zlcm(ZVALUE z1, ZVALUE z2, ZVALUE *res)
{
	ZVALUE temp1, temp2;

	zgcd(z1, z2, &temp1);
	zequo(z1, temp1, &temp2);
	zfree(temp1);
	zmul(temp2, z2, res);
	zfree(temp2);
}


/*
 * Return whether or not two numbers are relatively prime to each other.
 */
BOOL
zrelprime(ZVALUE z1, ZVALUE z2)
{
	FULL rem1, rem2;		/* remainders */
	ZVALUE rem;
	BOOL result;

	z1.sign = 0;
	z2.sign = 0;
	if (ziseven(z1) && ziseven(z2)) /* false if both even */
		return FALSE;
	if (zisunit(z1) || zisunit(z2)) /* true if either is a unit */
		return TRUE;
	if (ziszero(z1) || ziszero(z2)) /* false if either is zero */
		return FALSE;
	if (zistwo(z1) || zistwo(z2))	/* true if either is two */
		return TRUE;
	/*
	 * Try reducing each number by the product of the first few odd primes
	 * to see if any of them are a common factor.
	 */
	rem1 = zmodi(z1, (FULL)3 * 5 * 7 * 11 * 13);
	rem2 = zmodi(z2, (FULL)3 * 5 * 7 * 11 * 13);
	if (((rem1 % 3) == 0) && ((rem2 % 3) == 0))
		return FALSE;
	if (((rem1 % 5) == 0) && ((rem2 % 5) == 0))
		return FALSE;
	if (((rem1 % 7) == 0) && ((rem2 % 7) == 0))
		return FALSE;
	if (((rem1 % 11) == 0) && ((rem2 % 11) == 0))
		return FALSE;
	if (((rem1 % 13) == 0) && ((rem2 % 13) == 0))
		return FALSE;
	/*
	 * Try a new batch of primes now
	 */
	rem1 = zmodi(z1, (FULL)17 * 19 * 23);
	rem2 = zmodi(z2, (FULL)17 * 19 * 23);
	if (((rem1 % 17) == 0) && ((rem2 % 17) == 0))
		return FALSE;
	if (((rem1 % 19) == 0) && ((rem2 % 19) == 0))
		return FALSE;
	if (((rem1 % 23) == 0) && ((rem2 % 23) == 0))
		return FALSE;
	/*
	 * Yuk, we must actually compute the gcd to know the answer
	 */
	zgcd(z1, z2, &rem);
	result = zisunit(rem);
	zfree(rem);
	return result;
}


/*
 * Compute the integer floor of the log of an integer to a specified base.
 * The signs of the integers and base are ignored.
 * Example:  zlog(123456, 10) = 5.
 */
long
zlog(ZVALUE z, ZVALUE base)
{
	ZVALUE *zp;			/* current square */
	long power;			/* current power */
	ZVALUE temp;			/* temporary */
	ZVALUE squares[32];		/* table of squares of base */

	/* ignore signs */

	z.sign = 0;
	base.sign = 0;

	/*
	 * Make sure that the numbers are nonzero and the base is > 1
	 */
	if (ziszero(z) || ziszero(base) || zisone(base)) {
		math_error("Zero or too small argument argument for zlog!!!");
		/*NOTREACHED*/
	}

	/*
	 * Some trivial cases.
	 */
	power = zrel(z, base);
	if (power <= 0)
		return (power + 1);

	/* base - power of two */
	if (zisonebit(base))
		return (zhighbit(z) / zlowbit(base));

	/* base = 10 */
	if (base.len == 1 && base.v[0] == 10)
		return zlog10(z, NULL);
	/*
	 * Now loop by squaring the base each time, and see whether or
	 * not each successive square is still smaller than the number.
	 */
	zp = &squares[0];
	*zp = base;
	while (zp->len * 2 - 1 <= z.len  && zrel(z, *zp) > 0) {
		/* while square not too large */
		zsquare(*zp, zp + 1);
		zp++;
	}

	/*
	 * Now back down the squares,
	 */
	power = 0;
	for (; zp > squares; zp--) {
		if (zrel(z, *zp) >= 0) {
			zquo(z, *zp, &temp, 0);
			if (power)
				zfree(z);
			z = temp;
			power++;
		}
		zfree(*zp);
		power <<= 1;
	}
	if (zrel(z, *zp) >= 0)
		power++;
	if (power > 1)
		zfree(z);
	return power;
}


/*
 * Return the integral log base 10 of a number.
 *
 * If was_10_power != NULL, then this flag is set to TRUE if the
 * value was a power of 10, FALSE otherwise.
 */
long
zlog10(ZVALUE z, BOOL *was_10_power)
{
	ZVALUE *zp;			/* current square */
	long power;			/* current power */
	ZVALUE temp;			/* temporary */
	ZVALUE pow10;			/* power of 10 */
	FLAG rel;			/* relationship */
	int i;

	if (ziszero(z)) {
		math_error("Zero argument argument for zlog10");
		/*NOTREACHED*/
	}

	/* Ignore sign of z */
	z.sign = 0;

	/* preload power10 table if missing */
	if (power10 == NULL) {
		long v;

		/* determine power10 table size */
		for (v=1, max_power10_exp=0;
		     v <= (long)(MAXLONG/10L);
		     v *= 10L, ++max_power10_exp) {
		}

		/* create power10 table */
		power10 = malloc(sizeof(long) * (max_power10_exp+1));
		if (power10 == NULL) {
			math_error("cannot malloc power10 table");
			/*NOTREACHED*/
		}

		/* load power10 table */
		for (i=0, v = 1L; i <= max_power10_exp; ++i, v *= 10L) {
			power10[i] = v;
		}
	}

	/* assume not a power of ten unless we find out otherwise */
	if (was_10_power != NULL) {
		*was_10_power = FALSE;
	}

	/* quick exit for small values */
	if (! zgtmaxlong(z)) {
		long value = ztolong(z);

		for (i=0; i <= max_power10_exp; ++i) {
			if (value == power10[i]) {
				if (was_10_power != NULL) {
					*was_10_power = TRUE;
				}
				return i;
			} else if (value < power10[i]) {
				return i-1;
			}
		}
	}

	/*
	 * Loop by squaring the base each time, and see whether or
	 * not each successive square is still smaller than the number.
	 */
	zp = &_tenpowers_[0];
	*zp = _ten_;
	while (((zp->len * 2) - 1) <= z.len) {	/* while square not too large */
		if (zp >= &_tenpowers_[TEN_MAX]) {
			math_error("Maximum storable power of 10 reached!");
			/*NOTREACHED*/
		}
		if (zp[1].len == 0)
			zsquare(*zp, zp + 1);
		zp++;
	}

	/*
	 * Now back down the squares, and multiply them together to see
	 * exactly how many times the base can be raised by.
	 */
	/* find the tenpower table entry < z */
	do {
		rel = zrel(*zp, z);
		if (rel == 0) {
			/* quick exit - we match a tenpower entry */
			if (was_10_power != NULL) {
				*was_10_power = TRUE;
			}
			return (1L << (zp - _tenpowers_));
		}
	} while (rel > 0 && --zp >= _tenpowers_);
	if (zp < _tenpowers_) {
		math_error("fell off bottom of tenpower table!");
		/*NOTREACHED*/
	}

	/* the tenpower value is now our starting comparison value */
	zcopy(*zp, &pow10);
	power = (1L << (zp - _tenpowers_));

	/* try to build up a power of 10 from tenpower table entries */
	while (--zp >= _tenpowers_) {

		/* try the next lower tenpower value */
		zmul(pow10, *zp, &temp);
		rel = zrel(temp, z);
		if (rel == 0) {
			/* exact power of 10 match */
			power += (1L << (zp - _tenpowers_));
			if (was_10_power != NULL) {
				*was_10_power = TRUE;
			}
			return power;

		/* ignore this entry if we went too large */
		} else if (rel > 0) {
			zfree(temp);

		/* otherwise increase power and keep going */
		} else {
			power += (1L << (zp - _tenpowers_));
			zfree(pow10);
			pow10 = temp;
		}
	}
	return power;
}


/*
 * Return the number of times that one number will divide another.
 * This works similarly to zlog, except that divisions must be exact.
 * For example, zdivcount(540, 3) = 3, since 3^3 divides 540 but 3^4 won't.
 */
long
zdivcount(ZVALUE z1, ZVALUE z2)
{
	long count;		/* number of factors removed */
	ZVALUE tmp;		/* ignored return value */

	if (ziszero(z1) || ziszero(z2) || zisunit(z2))
		return 0;
	count = zfacrem(z1, z2, &tmp);
	zfree(tmp);
	return count;
}


/*
 * Remove all occurrences of the specified factor from a number.
 * Also returns the number of factors removed as a function return value.
 * Example:  zfacrem(540, 3, &x) returns 3 and sets x to 20.
 */
long
zfacrem(ZVALUE z1, ZVALUE z2, ZVALUE *rem)
{
	register ZVALUE *zp;		/* current square */
	long count;			/* total count of divisions */
	long worth;			/* worth of current square */
	long lowbit;			/* for zlowbit(z2) */
	ZVALUE temp1, temp2, temp3;	/* temporaries */
	ZVALUE squares[32];		/* table of squares of factor */

	z1.sign = 0;
	z2.sign = 0;
	/*
	 * Reject trivial cases.
	 */
	if ((z1.len < z2.len) || (zisodd(z1) && ziseven(z2)) ||
		ziszero(z2) || zisone(z2) ||
		((z1.len == z2.len) && (z1.v[z1.len-1] < z2.v[z2.len-1]))) {
		rem->v = alloc(z1.len);
		rem->len = z1.len;
		rem->sign = 0;
		zcopyval(z1, *rem);
		return 0;
	}
	/*
	 * Handle any power of two special.
	 */
	if (zisonebit(z2)) {
		lowbit = zlowbit(z2);
		count = zlowbit(z1) / lowbit;
		rem->v = alloc(z1.len);
		rem->len = z1.len;
		rem->sign = 0;
		zcopyval(z1, *rem);
		zshiftr(*rem, count * lowbit);
		ztrim(rem);
		return count;
	}
	/*
	 * See if the factor goes in even once.
	 */
	zdiv(z1, z2, &temp1, &temp2, 0);
	if (!ziszero(temp2)) {
		zfree(temp1);
		zfree(temp2);
		rem->v = alloc(z1.len);
		rem->len = z1.len;
		rem->sign = 0;
		zcopyval(z1, *rem);
		return 0;
	}
	zfree(temp2);
	z1 = temp1;
	/*
	 * Now loop by squaring the factor each time, and see whether
	 * or not each successive square will still divide the number.
	 */
	count = 1;
	worth = 1;
	zp = &squares[0];
	*zp = z2;
	while (((zp->len * 2) - 1) <= z1.len) { /* while square not too large */
		zsquare(*zp, &temp1);
		zdiv(z1, temp1, &temp2, &temp3, 0);
		if (!ziszero(temp3)) {
			zfree(temp1);
			zfree(temp2);
			zfree(temp3);
			break;
		}
		zfree(temp3);
		zfree(z1);
		z1 = temp2;
		*++zp = temp1;
		worth *= 2;
		count += worth;
	}

	/*
	 * Now back down the list of squares, and see if the lower powers
	 * will divide any more times.
	 */
	/*
	 * We prevent the zp pointer from walking behind squares
	 * by stopping one short of the end and running the loop one
	 * more time.
	 *
	 * We could stop the loop with just zp >= squares, but stopping
	 * short and running the loop one last time manually helps make
	 * code checkers such as insure happy.
	 */
	for (; zp > squares; zp--, worth /= 2) {
		if (zp->len <= z1.len) {
			zdiv(z1, *zp, &temp1, &temp2, 0);
			if (ziszero(temp2)) {
				temp3 = z1;
				z1 = temp1;
				temp1 = temp3;
				count += worth;
			}
			zfree(temp1);
			zfree(temp2);
		}
		if (zp != squares)
			zfree(*zp);
	}
	/* run the loop manually one last time */
	if (zp == squares) {
		if (zp->len <= z1.len) {
			zdiv(z1, *zp, &temp1, &temp2, 0);
			if (ziszero(temp2)) {
				temp3 = z1;
				z1 = temp1;
				temp1 = temp3;
				count += worth;
			}
			zfree(temp1);
			zfree(temp2);
		}
		if (zp != squares)
			zfree(*zp);
	}

	*rem = z1;
	return count;
}


/*
 * Keep dividing a number by the gcd of it with another number until the
 * result is relatively prime to the second number.  Returns the number
 * of divisions made, and if this is positive, stores result at res.
 */
long
zgcdrem(ZVALUE z1, ZVALUE z2, ZVALUE *res)
{
	ZVALUE tmp1, tmp2;
	long count, onecount;
	long sh;

	if (ziszero(z1) || ziszero(z2)) {
		math_error("Zero argument in call to zgcdrem!!!");
		/*NOTREACHED*/
	}
	/*
	 * Begin by taking the gcd for the first time.
	 * If the number is already relatively prime, then we are done.
	 */
	z1.sign = 0;
	z2.sign = 0;
	if (zisone(z2))
		return 0;
	if (zisonebit(z2)) {
		sh = zlowbit(z1);
		if (sh == 0)
			return 0;
		zshift(z1, -sh, res);
		return 1 + (sh - 1)/zlowbit(z2);
	}
	if (zisonebit(z1)) {
		if (zisodd(z2))
			return 0;
		*res = _one_;
		return zlowbit(z1);
	}

	zgcd(z1, z2, &tmp1);
	if (zisunit(tmp1) || ziszero(tmp1))
		return 0;
	zequo(z1, tmp1, &tmp2);
	count = 1;
	z1 = tmp2;
	z2 = tmp1;
	/*
	 * Now keep alternately taking the gcd and removing factors until
	 * the gcd becomes one.
	 */
	while (!zisunit(z2)) {
		onecount = zfacrem(z1, z2, &tmp1);
		if (onecount) {
			count += onecount;
			zfree(z1);
			z1 = tmp1;
		}
		zgcd(z1, z2, &tmp1);
		zfree(z2);
		z2 = tmp1;
	}
	*res = z1;
	return count;
}


/*
 * Return the number of digits (base 10) in a number, ignoring the sign.
 */
long
zdigits(ZVALUE z1)
{
	long count, val;

	z1.sign = 0;
	if (!zge16b(z1)) {	/* do small numbers ourself */
		count = 1;
		val = 10;
		while (*z1.v >= (HALF)val) {
			count++;
			val *= 10;
		}
		return count;
	}
	return (zlog10(z1, NULL) + 1);
}


/*
 * Return the single digit at the specified decimal place of a number,
 * where 0 means the rightmost digit.  Example:	 zdigit(1234, 1) = 3.
 */
long
zdigit(ZVALUE z1, long n)
{
	ZVALUE tmp1, tmp2;
	long res;

	z1.sign = 0;
	if (ziszero(z1) || (n < 0) || (n / BASEDIG >= z1.len))
		return 0;
	if (n == 0)
		return zmodi(z1, 10L);
	if (n == 1)
		return zmodi(z1, 100L) / 10;
	if (n == 2)
		return zmodi(z1, 1000L) / 100;
	if (n == 3)
		return zmodi(z1, 10000L) / 1000;
	ztenpow(n, &tmp1);
	zquo(z1, tmp1, &tmp2, 0);
	res = zmodi(tmp2, 10L);
	zfree(tmp1);
	zfree(tmp2);
	return res;
}


/*
 * z is to be a nonnegative integer
 * If z is the square of a integer stores at dest the square root of z;
 *	otherwise stores at z an integer differing from the square root
 *	by less than 1.	 Returns the sign of the true square root minus
 *	the calculated integer.	 Type of rounding is determined by
 *	rnd as follows: rnd = 0 gives round down, rnd = 1
 *	rounds up, rnd = 8 rounds to even integer, rnd = 9 rounds to odd
 *	integer, rnd = 16 rounds to nearest integer.
 */
FLAG
zsqrt(ZVALUE z, ZVALUE *dest, long rnd)
{
	HALF *a, *A, *b, *a0, u;
	int i, j, j1, j2, k, k1, m, m0, m1, n, n0, o;
	FULL d, e, f, g, h, s, t, x, topbit;
	int remsign;
	BOOL up, onebit;
	ZVALUE sqrt;

	if (z.sign) {
		math_error("Square root of negative number");
		/*NOTREACHED*/
	}
	if (ziszero(z)) {
		*dest = _zero_;
		return 0;
	}
	m0 = z.len;
	o = m0 & 1;
	m = m0 + o;		/* m is smallest even number >= z.len */
	n0 = n = m / 2;
	f = z.v[z.len - 1];
	k = 1;
	while (f >>= 2)
		k++;
	if (!o)
		k += BASEB/2;
	j = BASEB - k;
	m1 = m;
	if (k == BASEB) {
		m1 += 2;
		n0++;
	}
	A = alloc(m1);
	A[m1] = 0;
	a0 = A + n0;
	memcpy(A, z.v, m0 * sizeof(HALF));
	if (o)
		A[m - 1] = 0;
	if (n == 1) {
		if (j)
			f = (FULL) A[1] << j | A[0] >> k;
		else
			f = A[1];
		g = (FULL) A[0] << (j + BASEB);
		d = e = topbit = (FULL)1 << (k - 1);
	} else {
		if (j)
			f = (FULL) A[m-1] << (j + BASEB) | (FULL) A[m-2] << j |
				A[m-3] >> k;
		else
			f = (FULL) A[m-1] << BASEB | A[m-2];
		g = (FULL) A[m-3] << (j + BASEB) | (FULL) A[m-4] << j;
		d = e = topbit = (FULL)1 << (BASEB + k - 1);
	}

	s = (f & topbit);
	f <<= 1;
	if (g & TOPFULL)
		f++;
	g <<= 1;
	if (s) {
		f -= 4 * d;
		e = 2 * d - 1;
	}
	else
		f -= d;
	while (d >>= 1) {
		if (!(s | f | g))
			break;
		while (d && (f & topbit) == s) {
			d >>= 1;
			f <<= 1;
			if (g & TOPFULL)
				f++;
			g <<= 1;
		}
		if (d == 0)
			break;
		if (s)
			f += e + 1;
		else
			f -= e;
		t = f & topbit;
		f <<= 1;
		if (g & TOPFULL)
			f++;
		g <<= 1;
		if (t == 0 && f < d)
			t = topbit;
		f -= d;
		if (s)
			e -= d - !t;
		else
			e += d - (t > 0);
		s = t;
	}
	if (n0 == 1) {
		A[1] = (HALF)e;
		A[0] = (HALF)f;
		m = 1;
		goto done;
	}
	if (n0 == 2) {
		A[3] = (HALF)(e >> BASEB);
		A[2] = (HALF)e;
		A[1] = (HALF)(f >> BASEB);
		A[0] = (HALF)f;
		m = 2;
		goto done;
	}
	u = (HALF)(s ? BASE1 : 0);
	if (k < BASEB) {
		A[m1 - 1] = (HALF)(e >> (BASEB - 1));
		A[m1 - 2] = ((HALF)(e << 1) | (HALF)(s > 0));
		A[m1 - 3] = (HALF)(f >> BASEB);
		A[m1 - 4] = (HALF)f;
		m = m1 - 2;
		k1 = k + 1;
	} else {
		A[m1 - 1] = 1;
		A[m1 - 2] = (HALF)(e >> (BASEB - 1));
		A[m1 - 3] = ((HALF)(e << 1) | (HALF)(s > 0));
		A[m1 - 4] = u;
		A[m1 - 5] = (HALF)(f >> BASEB);
		A[m1 - 6] = (HALF)f;
		m = m1 - 3;
		k1 = 1;
	}
	h = e >> k;
	onebit = ((e & ((FULL)1 << (k - 1))) ? TRUE : FALSE);
	j2 = BASEB - k1;
	j1 = BASEB + j2;
	while (m > n0) {
		a = A + m - 1;
		if (j2)
			f = (FULL) *a << j1 | (FULL) a[-1] << j2 | a[-2] >> k1;
		else
			f = (FULL) *a << BASEB | a[-1];
		if (u)
			f = ~f;
		x = f / h;
		if (x) {
			if (onebit && x > 2 * (f % h) + 2)
				x--;
			b = a + 1;
			i = m1 - m;
			a -= i + 1;
			if (u) {
				f = *a + x * (BASE - x);
				*a++ = (HALF)f;
				u = (HALF)(f >> BASEB);
				while (i--) {
					f = *a + x * *b++ + u;
					*a++ = (HALF)f;
					u = (HALF)(f >> BASEB);
				}
				u += *a;
				x = ~x + !u;
				if (!(x & TOPHALF))
					a[1] -= 1;
			} else {
				f = *a - x * x;
				*a++ = (HALF)f;
				u = -(HALF)(f >> BASEB);
				while (i--) {
					f = *a - x * *b++ - u;
					*a++ = (HALF)f;
					u = -(HALF)(f >> BASEB);
				}
				u = *a - u;
				x = x + u;
				if (x & TOPHALF)
					a[1] |= 1;
			}
			*a = ((HALF)(x << 1) | (HALF)(u > 0));
		} else {
			*a = u;
		}
		m--;
		if (*--a == u) {
			while (m > 1 && *--a == u)
				m--;
		}
	}
	i = n;
	a = a0;
	while (i--) {
		*a >>= 1;
		if (a[1] & 1) *a |= TOPHALF;
		a++;
	}
	s = u;
done:	if (s == 0) {
		while (m > 0 && A[m - 1] == 0)
			m--;
		if (m == 0) {
			remsign = 0;
			sqrt.v = alloc(n);
			sqrt.len = n;
			sqrt.sign = 0;
			memcpy(sqrt.v, a0, n * sizeof(HALF));
			freeh(A);
			*dest = sqrt;
			return remsign;
		}
	}
	if (rnd & 16) {
		if (s == 0) {
			if (m != n) {
				up = (m > n);
			} else {
				i = n;
				b = a0 + n;
				a = A + n;
				while (i > 0 && *--a == *--b)
					i--;
				up = (i > 0 && *a > *b);
			}
		} else {
			while (m > 1 && A[m - 1] == BASE1)
				m--;
			if (m != n) {
				up = (m < n);
			} else {
				i = n;
				b = a0 + n;
				a = A + n;
				while (i > 0 && *--a + *--b == BASE1)
					i--;
				up = ((FULL) *a + *b >= BASE);
			}
		}
	}
	else
	if (rnd & 8)
		up = (((rnd ^ *a0) & 1) ? TRUE : FALSE);
	else
		up = ((rnd & 1) ? TRUE : FALSE);
	if (up) {
		remsign = -1;
		i = n;
		a = a0;
		while (i-- && *a == BASE1)
			*a++ = 0;
		if (i >= 0) {
			(*a)++;
		} else {
			n++;
			*a = 1;
		}
	} else {
		remsign = 1;
	}
	sqrt.v = alloc(n);
	sqrt.len = n;
	sqrt.sign = 0;
	memcpy(sqrt.v, a0, n * sizeof(HALF));
	freeh(A);
	*dest = sqrt;
	return remsign;

}

/*
 * Take an arbitrary root of a number (to the greatest integer).
 * This uses the following iteration to get the Kth root of N:
 *	x = ((K-1) * x + N / x^(K-1)) / K
 */
void
zroot(ZVALUE z1, ZVALUE z2, ZVALUE *dest)
{
	ZVALUE ztry, quo, old, temp, temp2;
	ZVALUE k1;			/* holds k - 1 */
	int sign;
	long i;
	LEN highbit, k;
	SIUNION sival;

	sign = z1.sign;
	if (sign && ziseven(z2)) {
		math_error("Even root of negative number");
		/*NOTREACHED*/
	}
	if (ziszero(z2) || zisneg(z2)) {
		math_error("Non-positive root");
		/*NOTREACHED*/
	}
	if (ziszero(z1)) {	/* root of zero */
		*dest = _zero_;
		return;
	}
	if (zisunit(z2)) {	/* first root */
		zcopy(z1, dest);
		return;
	}
	if (zge31b(z2)) {	/* humongous root */
		*dest = _one_;
		dest->sign = (BOOL)((HALF)sign);
		return;
	}
	k = (LEN)ztolong(z2);
	highbit = zhighbit(z1);
	if (highbit < k) {	/* too high a root */
		*dest = _one_;
		dest->sign = (BOOL)((HALF)sign);
		return;
	}
	sival.ivalue = k - 1;
	k1.v = &sival.silow;
	/* ignore Saber-C warning #112 - get ushort from uint */
	/*	  ok to ignore on name zroot`sival */
	k1.len = 1 + (sival.sihigh != 0);
	k1.sign = 0;
	z1.sign = 0;
	/*
	 * Allocate the numbers to use for the main loop.
	 * The size and high bits of the final result are correctly set here.
	 * Notice that the remainder of the test value is rubbish, but this
	 * is unimportant.
	 */
	highbit = (highbit + k - 1) / k;
	ztry.len = (highbit / BASEB) + 1;
	ztry.v = alloc(ztry.len);
	zclearval(ztry);
	ztry.v[ztry.len-1] = ((HALF)1 << (highbit % BASEB));
	ztry.sign = 0;
	old.v = alloc(ztry.len);
	old.len = 1;
	zclearval(old);
	old.sign = 0;
	/*
	 * Main divide and average loop
	 */
	for (;;) {
		zpowi(ztry, k1, &temp);
		zquo(z1, temp, &quo, 0);
		zfree(temp);
		i = zrel(ztry, quo);
		if (i <= 0) {
			/*
			 * Current try is less than or equal to the root since it is
			 * less than the quotient. If the quotient is equal to the try,
			 * we are all done.  Also, if the try is equal to the old value,
			 * we are done since no improvement occurred.
			 * If not, save the improved value and loop some more.
			 */
			if ((i == 0) || (zcmp(old, ztry) == 0)) {
				zfree(quo);
				zfree(old);
				ztry.sign = (BOOL)((HALF)sign);
				zquicktrim(ztry);
				*dest = ztry;
				return;
			}
			old.len = ztry.len;
			zcopyval(ztry, old);
		}
		/* average current try and quotient for the new try */
		zmul(ztry, k1, &temp);
		zfree(ztry);
		zadd(quo, temp, &temp2);
		zfree(temp);
		zfree(quo);
		zquo(temp2, z2, &ztry, 0);
		zfree(temp2);
	}
}


/*
 * Test to see if a number is an exact square or not.
 */
BOOL
zissquare(ZVALUE z)
{
	long n;
	ZVALUE tmp;

	/* negative values are never perfect squares */
	if (zisneg(z)) {
		return FALSE;
	}

	/* ignore trailing zero words */
	while ((z.len > 1) && (*z.v == 0)) {
		z.len--;
		z.v++;
	}

	/* zero or one is a perfect square */
	if (zisabsleone(z)) {
		return TRUE;
	}

	/* check mod 4096 values */
	if (issq_mod4k[(int)(*z.v & 0xfff)] == 0) {
		return FALSE;
	}

	/* must do full square root test now */
	n = !zsqrt(z, &tmp, 0);
	zfree(tmp);
	return (n ? TRUE : FALSE);
}
